#include "../include/gudb.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/stat.h>

// Test utility functions
static void test_print(const char* test_name, int success) {
    printf("[%s] %s\n", success ? "PASS" : "FAIL", test_name);
}

static int cleanup_test_dir(const char* dir) {
    char cmd[512];
    snprintf(cmd, sizeof(cmd), "rm -rf %s", dir);
    return system(cmd);
}

// Test CREATE INDEX and DROP INDEX functionality
static int test_index_operations() {
    printf("\n=== Testing Index Operations ===\n");
    
    const char* test_dir = "./test_index_db";
    int success = 1;
    
    // Clean up any existing test directory
    cleanup_test_dir(test_dir);
    
    // Test database creation and opening
    gudb* db = gudb_open(test_dir, GU_OPEN_CREATE | GU_OPEN_READWRITE, "admin", "password");
    if (!db) {
        printf("Failed to open database: %s\n", gudb_error(NULL));
        return 0;
    }
    test_print("Database Open", 1);
    
    // Begin a transaction
    gudb_txn* txn = gudb_begin(db, 0, NULL);
    if (!txn) {
        printf("Failed to begin transaction\n");
        gudb_close(db);
        return 0;
    }
    test_print("Begin Transaction", 1);
    
    result_t* result = NULL;
    
    // Create test database
    int exec_result = gudb_exec(txn, "CREATE DATABASE testdb", NULL, &result);
    test_print("Create Database", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Use test database
    exec_result = gudb_exec(txn, "USE testdb", NULL, &result);
    test_print("Use Database", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Create a test table
    exec_result = gudb_exec(txn, "CREATE TABLE users (id INT, name VARCHAR(50), email VARCHAR(100))", NULL, &result);
    test_print("Create Table", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Test CREATE INDEX - basic syntax
    exec_result = gudb_exec(txn, "CREATE INDEX idx_user_id ON users (id)", NULL, &result);
    test_print("Create Index on ID", exec_result == GU_OK);
    if (exec_result != GU_OK) {
        printf("   Error code: %d, Message: %s\n", exec_result, gudb_txn_error(txn) ? gudb_txn_error(txn) : "No error message");
    }
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Test CREATE UNIQUE INDEX
    exec_result = gudb_exec(txn, "CREATE UNIQUE INDEX idx_user_email ON users (email)", NULL, &result);
    test_print("Create Unique Index on Email", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Test CREATE INDEX with multiple columns
    exec_result = gudb_exec(txn, "CREATE INDEX idx_user_name_email ON users (name, email)", NULL, &result);
    test_print("Create Multi-Column Index", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Test CREATE INDEX IF NOT EXISTS
    exec_result = gudb_exec(txn, "CREATE INDEX IF NOT EXISTS idx_user_id ON users (id)", NULL, &result);
    test_print("Create Index IF NOT EXISTS (should succeed)", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Test CREATE INDEX with existing name (should fail)
    exec_result = gudb_exec(txn, "CREATE INDEX idx_user_id ON users (name)", NULL, &result);
    test_print("Create Index with Existing Name (should fail)", exec_result != GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Test DROP INDEX
    exec_result = gudb_exec(txn, "DROP INDEX idx_user_id", NULL, &result);
    test_print("Drop Index", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Test DROP INDEX IF EXISTS
    exec_result = gudb_exec(txn, "DROP INDEX IF EXISTS idx_user_id", NULL, &result);
    test_print("Drop Index IF EXISTS (should succeed)", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Test DROP INDEX with non-existent index (should fail)
    exec_result = gudb_exec(txn, "DROP INDEX nonexistent_index", NULL, &result);
    test_print("Drop Non-existent Index (should fail)", exec_result != GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Drop remaining indexes
    exec_result = gudb_exec(txn, "DROP INDEX idx_user_email", NULL, &result);
    test_print("Drop Email Index", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    exec_result = gudb_exec(txn, "DROP INDEX idx_user_name_email", NULL, &result);
    test_print("Drop Multi-Column Index", exec_result == GU_OK);
    if (result) {
        gudb_free_result(result);
        result = NULL;
    }
    
    // Commit transaction
    int commit_result = gudb_commit(txn);
    test_print("Commit Transaction", commit_result == GU_OK);
    
    // Close database
    int close_result = gudb_close(db);
    test_print("Database Close", close_result == GU_OK);
    if (close_result != GU_OK) {
        success = 0;
    }
    
    // Clean up
    cleanup_test_dir(test_dir);
    
    return success;
}

int main() {
    printf("GuDB Index Functionality Test Suite\n");
    printf("===================================\n");
    
    int all_tests_passed = 1;
    
    // Run index operations test
    if (!test_index_operations()) {
        all_tests_passed = 0;
    }
    
    printf("\n=== Test Summary ===\n");
    printf("Overall Result: %s\n", all_tests_passed ? "ALL TESTS PASSED" : "SOME TESTS FAILED");
    
    return all_tests_passed ? 0 : 1;
}